/************************************
 *
 *
 * Dinamico
 * v0.10.1
 * jiturbe
 *
 *
 *
 *
 * Notas de la version 0.3
 *
 * *Hay que ajustar el tamano de A con el tamano de id_vector e ids
 * *Cuando se elimine tiene que ser del tamano de id_vector
 * ** A=gsl_matrix_alloc(id_vector.size(),n);
 * *Se deja la matiz A crecer o decrecer segun corresponda 
 * *tener en cuenta que existe una asimetria muy grande entre lo normal (la mayoria) y lo anormal (muy poco)
 *
 * Notas de la version 0.4
 *
 * * Se elimina definitivamente cells[i] y se reemplaza por ids[i][0]
 * * m no se ocupa
 * * problema por los identificadores de las celulas al recalcular el A. ?Nuevo campo posision en celula?
 * * no se esta revisando el tamano de memoria del y [1....m][q]
 * * gsl: svd.c:61: ERROR: svd of MxN matrix, M<N, is not implemented
 *
 * Notas de la version 0.5
 * * Cuando se hace anormal una celula su edad se vuelve a 0 (Algo anormal en un comienzo, puede volverse normal?)
 *
 *
 * Notas de la version 0.8
 * * Se agrega la funcion de recibir un archivo con los resultados verdaderos (-v <resultados_verdaderos>)
 * * Se asume que si el numero de resultados_verdaderos es menor al que se obtiene, el resto de los resultados es 0 (normal)
 * * Se agrega ordenar resultados
 * * Se agrega resumir resultados
 *
 * Notas de la version 0.9.0
 * * Se agrega el parametro envejecido, umbral para decidir si las celulas normales se eliminan al cumplir una edad
 * * Se empieza a controlar la edad de la celula
 *
 * Notas de la version 0.9.1
 * * Se agrega el detalle de la tabla de contingencia 
 * * Se agrega la apoptosis e inmunizacion en etapa de entrenamiento
 * * El inicio del fin ahora es despues del entrenamiento
 *
 * Notas de la version 0.9.2
 * * Se agrega el entrenamiento en un archivo separado
 * * Se agregan los resultados en el directorio resultados, ordenados por fecha
 *
 * Notas de la version 0.9.3
 * * Se agrega la estimulacion de la normalidad
 * * Se agrega max_count
 *
 * Notas de la version 0.10.1
 * * Inciertos al FIN
 *
 * Notas de la version 0.10.2
 * * Calculo de porcentajes de los grupos inciertos: normales vs anormales
 * * Tasa de crecimiento de los conjuntos
 *
 */




#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <sstream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <ctime>
#include <stdlib.h>
#include <map>
#include <vector>
#include <algorithm>
#include <stdio.h>



#include <gsl/gsl_errno.h>
#include <gsl/gsl_vector.h>
#include <gsl/gsl_matrix.h>
#include "gsl/gsl_linalg.h"


using namespace std;

int n,m,q,debug;
float umbral_afinidad;
float umbral_reconocimiento;
int umbral_transformacion;
gsl_vector *work,*V_S;
gsl_matrix *A,*R, *S, *Original,*y;
gsl_matrix *y_matrix,*entrante_matrix;
map<string,string> p_tiempos; 
int anormales_enlinea;
int normales_enlinea;

ofstream tdc("tabla_de_contingencia.dat",ios::out);
ofstream tasa("estadisticas/tasa.log",ios::out);
ofstream tasas("estadisticas/tasas.csv",ios::out);
class Celula
{
public:

   int id;     //Identificador de la celula
   double x;   //Coordanada x
   double y;   //Coordenada y
   double z;   //Coordenada z
   int f;      //el tipo, puede ser f=0 => normal; f=1 => incierto; f=2 => anormal
//   int estado; // 0: muerta ; 1: viva
   int edad;   //edad de la celula
   int grupo;
   int region;
   int mas_cercana;
   double distancia;
   int normal;
   int anormal;
   int incierto;
   int clasifica;
   vector<double> t_c;
   int tamano_anterior;
   Celula(double xx, double yy, double zz, int ff, int r,double d, int m)
   {
     x=xx;
     y=yy;
     z=zz;
     f=ff;
     region=r;
     distancia=d;
     //estado=e;
     edad=0;
     grupo=0;
     mas_cercana=m;
   }

   Celula(){;}
};

class Tabla_de_contingencia
{
public:
   int id; 
   int vp; 
   int vn; 
   int fp; 
   int fn; 
   int otro;
   int incierto;
   int total;


Tabla_de_contingencia(int idd)
{   
  id=idd;
  vp=0;
  vn=0;
  fp=0;
  fn=0;
  otro=0;
  incierto=0;
}   

Tabla_de_contingencia(){
						          
								     
  vp=0;
  vn=0;
  fp=0;
  fn=0;
  total=0;
}   
};




int split(vector<string>& v, const string& str, char c)
{
   v.clear();
   string::const_iterator s = str.begin();
   while (true) {

      string::const_iterator begin = s;
      while (*s != c && s != str.end()) { ++s; }
      v.push_back(string(begin, s));
      if (s == str.end()) {
         break;
      }
      if (++s == str.end()) {
         v.push_back("");
         break;
      }
   }
}

const bool isdouble(const std::string& s)

{

  std::istringstream i(s);

    double temp;

      return ( (i >> temp) ? true : false );

}

void resume(map<int,int> verdaderos,map<int,int> obtenidos, map<string,string> p_resumen,int t){


//ifstream parametros2("parametros.dat");
ofstream log_resumen("log/resumen.log",ios::out);
ofstream resultados("resultados.csv",ios::out);
ofstream tiempos("estadisticas/tiempos.csv",ios::out);
time_t comienzo, final, now;
struct tm *tiempoComienzoPtr, *tiempoFinalPtr, *ahoraPtr;
struct tm *tm;
int largo=200;
char *s,*comando;

now = time ( NULL );
tm = localtime ( &now );

s = new char[largo];
strftime ( s, largo, "resultados/%d-%B-%Y_%H-%M-%S", tm );
cout << s << endl;


comando = new char[largo];


sprintf(comando,"mkdir -p %s",s);

system(comando);

map< int, Tabla_de_contingencia> tabla;
map< int, Tabla_de_contingencia> tabla_o;

int vp=0;
int vn=0;
int fp=0;
int fn=0;
int otro=0;
int incierto=0;
int tam=verdaderos.size();
string linea;
/*
tdc << "PARAMETROS" << endl;

while(!parametros2.eof()){

     getline(parametros2,linea);
     tdc << linea << endl;

}
*/
if(debug==1)
log_resumen << "tamano verdaderos: " << tam << endl;

tdc << "TABLA DE CONTINGENCIA" << endl;
resultados << "ID,Obtenido,Verdadero" << endl;


cout <<  "El tamano de los obtenidos es: " << obtenidos.size() << endl;
cout << "El tamano de los verdadero es: " << verdaderos.size() << endl;

if(obtenidos.size()!=verdaderos.size())
	cout << "ADVERTENCIA: El tamano de los obtenidos difiere de los verdaderos... REVISAR!!!" << endl;


for(int i=0;i<tam;i++){
if(debug==1)
 log_resumen << i << ": ";

  resultados << (i+t) << "," << obtenidos[i] << "," << verdaderos[i] << endl;


 if(0 < obtenidos[i] && 0 < verdaderos[i]){

// if((0 < obtenidos[i] < 39 || obtenidos[i]==verdaderos[i]) && verdaderos[i]!=0 && verdaderos[i]!=39){
// if((obtenidos[i] == 37 || obtenidos[i]==verdaderos[i]) && verdaderos[i]!=0 && verdaderos[i]!=39){
// if( obtenidos[i] == 37 && 0 < verdaderos[i] < 39 || (obtenidos[i] == verdaderos[i]&& obtenidos[i] != 0)){
if(debug==1)   
log_resumen << "Verdadero Positivo: " <<  obtenidos[i] << " & " << verdaderos[i] << endl;
   vp++;
   tabla[verdaderos[i]].vp++;
   tabla_o[obtenidos[i]].vp++;

 }else if( obtenidos[i]==0 && verdaderos[i]==0){

if(debug==1)   
   log_resumen << "Verdadero Negativo: " <<  obtenidos[i] << " & " << verdaderos[i] << endl;
   vn++;
   tabla[verdaderos[i]].vn++;
   tabla_o[obtenidos[i]].vn++;

// }else if( 0<obtenidos[i]<39 && verdaderos[i]==0 || (obtenidos[i] !=verdaderos[i] && obtenidos[i]!=0 && verdaderos[i]!=0) ){ //jiturbe: check!

 }else if( 0<obtenidos[i] && verdaderos[i]==0 ){ //jiturbe: check!

if(debug==1)   
   log_resumen << "Falso Positivo: " <<  obtenidos[i] << " & " << verdaderos[i] << endl;
   fp++;
   tabla[verdaderos[i]].fp++;

   tabla_o[obtenidos[i]].fp++;
 }else if( obtenidos[i]==0 && 0 < verdaderos[i]){

if(debug==1)   
   log_resumen << "Falso Negativo: " <<  obtenidos[i] << " & " << verdaderos[i] << endl;
   fn++;
   tabla[verdaderos[i]].fn++;

   tabla_o[obtenidos[i]].fn++;
 }else if(obtenidos[i]==-1){


if(debug==1)   
   log_resumen << "Incierto: " <<  obtenidos[i] << " & " << verdaderos[i] << endl;
   incierto++;
   tabla[verdaderos[i]].incierto++;


 }else{


if(debug==1)   
   log_resumen << "Otro: " <<  obtenidos[i] << " & " << verdaderos[i] << endl;
   otro++;
   tabla[verdaderos[i]].otro++;


 }

}


int total=vp+vn+fn+fp;

double exactitud=(double)(vp+vn)/total;
double error = (double)(fp+fn)/total;
double sensibilidad = (double)vp/(vp+fn);
double especificidad = (double)vn/(fp+vn);
double vpp= (double)vp/(vp+fp);
double vpn= (double)vn/(vn+fn);




cout << "RESULTADOS" << endl << endl;
cout << "De un total de " << total << " + inciertos " << incierto << " + otros " << otro << " = " << (tam) << endl << endl;
cout << vp << " Verdaderos Positivos." << endl;//Dio anormal y era anormal 
cout << fp << " Falsos Positivos." << endl;    //Dio anormal y era normal
cout << fn << " Falsos Negativos." << endl;    //Dio normal  y era anormal
cout << vn << " Verdaderos Negativos." << endl << endl;//Dio normal y era normal
cout << otro << " Otros." << endl << endl;
cout << incierto << " Inciertos." << endl << endl;
cout << "vp+fp = " << vp + fp << endl;

cout << "fn+vn = " << fn + vn << endl;

cout << "vp+fn = " << vp + fn << endl;
cout << "fp+vn = " << fp + vn << endl;


cout << "Exactitud = " << exactitud << endl;
cout << "Error = " << error << endl;
cout << "Sensibilidad = " << sensibilidad << endl;
cout << "Especificidad = " << especificidad << endl;
cout << "Valor predictivo: Positivo = " << vpp << endl;
cout << "Valor predictivo: Negativo = " << vpn << endl;



cout << endl;
cout << endl;


tdc << "RESULTADOS" << endl << endl;

tdc << "De un total de " << total << " + inciertos " << incierto << " + otros " <<  otro << " = " << (tam) << endl << endl;
tdc << vp << " Verdaderos Positivos." << endl;//Dio anormal y era anormal 
tdc << fp << " Falsos Positivos." << endl;    //Dio anormal y era normal
tdc << fn << " Falsos Negativos." << endl;    //Dio normal  y era anormal
tdc << vn << " Verdaderos Negativos." << endl << endl;//Dio normal y era normal
tdc << incierto << " Inciertos." << endl << endl;
tdc << otro << " Otros." << endl << endl;
tdc << "vp+fp = " << vp + fp << endl;


tdc << "vp+fp = " << vp + fp << endl;

tdc << "fn+vn = " << fn + vn << endl;

tdc << "vp+fn = " << vp + fn << endl;
tdc << "fp+vn = " << fp + vn << endl;


tdc << "Exactitud = " << exactitud << endl;
tdc << "Error = " << error << endl;
tdc << "Sensibilidad = " << sensibilidad << endl;
tdc << "Especificidad = " << especificidad << endl;
tdc << "Valor predictivo: Positivo = " << vpp << endl;
tdc << "Valor predictivo: Negativo = " << vpn << endl;
tdc << endl;
tdc << endl;


ofstream detalle("tdc_detalle.csv",ios::app);

ofstream tdc_detalle("estadisticas/tdc_detalle.resultado",ios::out);

map < int, Tabla_de_contingencia >::iterator iter;

tdc_detalle << "id,vp,fp,fn,vn" << endl;

for(iter=tabla.begin();iter!=tabla.end();iter++)
{

     tdc_detalle << iter->first << "," << iter->second.vp << "," << iter->second.fp << "," << iter->second.fn << "," << iter->second.vn << endl;

}



tdc_detalle << endl << "=============================" << endl;

int h=0;

for(iter=tabla_o.begin();iter!=tabla_o.end();iter++)
{

     tdc_detalle << iter->first << "," << iter->second.vp << "," << iter->second.fp << "," << iter->second.fn << "," << iter->second.vn << endl;


     if(iter->first==0){

		detalle << iter->second.fn << ",";

     }else{

	if( iter->first == h  ){

		detalle << iter->second.fp << ",";

	}else{

	  for(int g=h;g<iter->first;g++){

		detalle << "0,";

	  }
	  h=iter->first;

	  detalle << iter->second.fp << ",";

		
	}

     }

	  h++;

}
detalle << endl;

map<string,string>::iterator iter_tiempo;

for(iter_tiempo=p_tiempos.begin();iter_tiempo!=p_tiempos.end();iter_tiempo++){

  tiempos << iter_tiempo->first << "," << iter_tiempo->second << endl;

}



map<string,string>::iterator iter_param;

ofstream param("estadisticas/parametros-dump.dat",ios::out);

for(iter_param=p_resumen.begin();iter_param!=p_resumen.end();iter_param++){

  param << iter_param->first << "=" << iter_param->second << endl;

}




ofstream resumen("resumen_total.csv",ios::app);


//resumen << "Datos,umbral_afinidad,n_watch,min_count," << endl;

resumen << p_resumen["estatico"] << "," << p_resumen["t_total"] << "," << s << "," << p_resumen["parametros"] << "," << p_resumen["tipos_verdaderos"] << "," << p_resumen["datos_entrenamiento"] << "," << p_resumen["n_watch"] << "," << p_resumen["min_count"] << "," << p_resumen["max_count"] << "," << p_resumen["envejecido"] << "," << p_resumen["umbral_transformacion"] << "," << p_resumen["umbral_afinidad"] << "," << p_resumen["umbral_reconocimiento"] << "," << vp << "," << fp << "," << fn << "," << vn << "," << exactitud << "," << error << "," << sensibilidad << "," << especificidad << "," <<  endl;

sprintf(comando,"cp tdc_detalle.resultado %s/tdc_detalle.csv",s);
system(comando);
//sprintf(comando,"cp parametros-dump.dat %s/%s",s,p_resumen["parametros"].c_str());
//system(comando);
sprintf(comando,"cp tabla_de_contingencia.dat %s/tabla_de_contingencia.dat",s);
system(comando);
sprintf(comando,"cp resultados.csv %s/resultados.csv",s);
system(comando);
sprintf(comando,"cp -rf estadisticas %s/estadisticas",s);
system(comando);


}



map < int, vector<Celula> > apoptosis(map < int, vector<Celula> > cells){

  ofstream log_apoptosis("log/apoptosis.log", ios::out);
  time_t comienzo, final;
  Celula mas_cercana;
  double xd,yd,zd,distancia_cercana,dist_aux;

comienzo = time( NULL );

if(debug==1)
log_apoptosis << "Calculando Apoptosis..." << endl;

if(debug==1)
log_apoptosis << "Las vivas actuales son: " << cells.size() << endl;
cout << "Calculando Apoptosis..." << endl;

cout << "Las vivas actuales son: " << cells.size() << endl;


map < int, vector<Celula> >::iterator iter;
map < int, vector<Celula> >::iterator iter2;

map < int, vector<Celula> >::iterator iter_aux;

map < int, vector<Celula> >::iterator iter3;

for(iter=cells.begin();iter!=cells.end();iter++){

if(debug==1){
  log_apoptosis << "iter->first " << iter->first << endl;

  log_apoptosis << "iter->second.id " << iter->second[0].id << endl;
  log_apoptosis << "iter->second.f " << iter->second[0].f << endl;
}

//if(iter->second[0].estado==1){
    distancia_cercana=1000;

   if(iter->second[0].f!=-1)
    for(iter2=cells.begin();iter2!=cells.end();iter2++){

      if(iter->second[0].id!=iter2->second[0].id && iter2->second[0].f!=-1){

        xd=iter2->second[0].x-iter->second[0].x;
        yd=iter2->second[0].y-iter->second[0].y;
        zd=iter2->second[0].z-iter->second[0].z;
        dist_aux=xd*xd+yd*yd+zd*zd;
        dist_aux=sqrt(dist_aux);

        if(dist_aux<distancia_cercana ){
            mas_cercana=iter2->second[0];
            distancia_cercana=dist_aux;

        }
      }
    }


if(debug==1){
log_apoptosis << "i: " << iter->first << "\n x: " << iter->second[0].x << " y: " << iter->second[0].y << " z: " << iter->second[0].z <<" f: " << iter->second[0].f << endl;

log_apoptosis << "mas_cercana: " << mas_cercana.id << "\n x: " << mas_cercana.x << " y: " << mas_cercana.y << " z: " << mas_cercana.z <<" f: " << mas_cercana.f << endl;

log_apoptosis << "Los mas cercano " << iter->second[0].id << "-" << mas_cercana.id << " | " << distancia_cercana  << endl;
}

   if(distancia_cercana<umbral_afinidad && iter->second[0].f == mas_cercana.f&&iter->second[0].f!=-1){

	if(iter->second[0].f==0){
		normales_enlinea--;
	}else{
		anormales_enlinea--;
	}


	cells.erase(iter);
   }
// }
	//cout << "A: normales: " << normales_enlinea << " anormales: " << anormales_enlinea << endl;
}


final = time( NULL );

char aux[15];

sprintf(aux,"%f",difftime(final,comienzo));


p_tiempos["t_apoptosis"]=aux;


if(debug==1)
log_apoptosis << "Tiempo apoptosis: " << difftime(final, comienzo) << endl << endl;

tdc << "Tiempo apoptosis: " << difftime(final, comienzo) << endl << endl;

//cout << "Tiempo apoptosis: " << difftime(final, comienzo) << endl << endl;

if(debug==1)
log_apoptosis << "Vivos despues apoptosis " << cells.size() << endl;
tdc << "Vivos despues apoptosis " << cells.size() << endl;

//cout << "Vivos despues apoptosis " << cells.size() << endl;

ofstream celulas_apoptosis("celulas_apoptosis.csv",ios::out);

for(iter3=cells.begin();iter3!=cells.end();iter3++){

celulas_apoptosis << iter3->second[0].x << "," << iter3->second[0].y << "," << iter3->second[0].z << endl;

if(debug==1)
log_apoptosis << iter3->second[0].id << "," << iter3->second[0].x << "," << iter3->second[0].y << "," << iter3->second[0].z << endl;
//log << iter3->second[0].id << endl; 

}


return cells;
}






map < int, vector<Celula> > inmunizacion(map < int, vector<Celula> > cells, map <int, vector<Celula> > copia_cells){

  time_t comienzo, final;
  Celula mas_cercana;
  double xd,yd,zd,distancia_cercana,dist_aux;


	//cout << "ENTRO A I: normales: " << normales_enlinea << " + anormales: " << anormales_enlinea << " = tamano: " << cells.size() << endl;
map < int, vector<Celula> >::iterator iter;
map < int, vector<Celula> >::iterator iter2;
map < int, vector<Celula> >::iterator iter_aux;

ofstream log("log/inmunizacion.log",ios::out);


comienzo = time(NULL);
//cout << "Calculando Inmunizacion..." << endl;

int lll=0;

for(iter=cells.begin();iter!=cells.end();iter++){

lll++;

  distancia_cercana=1000.0;
if(debug==1)  {
  log << "iter->first " << iter->first << endl;
  log << "iter->second.id " << (iter->second)[0].id << endl;
  log << "iter->second.f " << (iter->second)[0].f << endl;
}	
//  log << "iter->second.id " << ((*iter).second).id << endl;
  if((iter->second)[0].f!=-1)
  for(iter2=copia_cells.begin();iter2 != copia_cells.end();iter2++){
	    
     if( iter->first!=iter2->first && iter2->second[0].f!=-1){
        xd=(iter2->second)[0].x-(iter->second)[0].x;
        yd=(iter2->second)[0].y-(iter->second)[0].y;
        zd=(iter2->second)[0].z-(iter->second)[0].z;
        dist_aux=xd*xd+yd*yd+zd*zd;
        dist_aux=sqrt(dist_aux);
			      
        if(dist_aux<distancia_cercana){
           iter_aux=iter2;
           distancia_cercana=dist_aux;
        }
     }
  }

if(debug==1){										
  log << "Inmunizacion" << endl;
  log << "i: " << iter->first << "\n x: " << iter->second[0].x << " y: " << iter->second[0].y << " z: " << iter->second[0].z <<" f: " << iter->second[0].f << endl;
  log << "mas_cercana: " << iter_aux->first << "\n x: " << iter_aux->second[0].x << " y: " << iter_aux->second[0].y << " z: " << iter_aux->second[0].z <<" f: " << iter_aux->second[0].f << endl;
  log << "Los mas cercano |" << iter->first << "-" << iter_aux->first << " | :=" << distancia_cercana  << endl;
}



  if( distancia_cercana<umbral_afinidad && (iter->second)[0].f != (iter_aux->second)[0].f && iter->second[0].f!=-1 && cells[iter_aux->first].empty()){

if(debug==1)
	log << "Se agrega la celula id " << iter_aux->first << endl;
	
	if(!cells[iter_aux->first].empty()){

if(debug==1)
		log << "existe!!" << endl;

	}


        cells[iter_aux->first].push_back((iter_aux->second)[0]);
//          cells[iter_aux->second[0].id].push_back((iter_aux->second)[0]);

	if(iter_aux->second[0].f==0){
		normales_enlinea++;
	}else{
		anormales_enlinea++;
	}


  }

if(debug==1)
	log << "I: normales: " << normales_enlinea << " + anormales: " << anormales_enlinea << " = tamano: " << cells.size() << endl;
}

fprintf( stderr, "got to line %d\n", __LINE__ );
final = time( NULL );

char aux[10];

sprintf(aux,"%f",difftime(final,comienzo));

p_tiempos["t_inmunizacion"]=aux;



printf( "Inmunizacion: %f s\n", difftime(final, comienzo) );
//cout << "Vivos despues inmunizacion " << cells.size() << endl;
//cout << "lll: " << lll << endl;


return cells;


}

void celulas(map < int, vector<Celula> > cells){

map <int,vector<Celula> >::iterator iter;
ofstream salida("estadisticas/cells_ids.csv",ios::out);


	for(iter=cells.begin();iter!=cells.end();iter++){


		salida << iter->second[0].x << " " << iter->second[0].y << " " << iter->second[0].z << " " << iter->second[0].f << endl;



	}







}

void estadisticas(map < int, vector<Celula> > ids,map<int,int> verdaderos, map<int,int> obtenidos,int t,map <int,int> e_ataque,map <int,int> e_region){

//cout << __LINE__ << endl;
ofstream estad("estadisticas/fin.csv",ios::out);
ofstream estad_r("estadisticas/region.csv",ios::out);
ofstream estad_2("estadisticas/regiones.csv",ios::out);



//cout << __LINE__ << endl;



map <int,int>::iterator iter_a;
map <int,int>::iterator iter_e;
map < int, vector<Celula> >::iterator iter;
map < int, vector<Celula> >::iterator iter_2;
vector<Celula>::iterator it_cel;
vector<double>::iterator it_tc;

//cout << __LINE__ << endl;
//map < int, vector<Celula> >::iterator iter4;
vector<Celula>::iterator iter2;

/*
  for(iter4=ids.begin();iter4!=ids.end();iter4++){


    e_region[(iter4->second)[0].region]=0;
  }
*/


cout << __LINE__ << endl;
    estad << "id,region,obtenido,tamano,verdadero" << endl;

cout << __LINE__ << endl;
  for(iter=ids.begin();iter!=ids.end();iter++){

    estad << iter->first << "," << (iter->second)[0].region << "," << (iter->second)[0].f << "," << ids[iter->first].size() << "," << verdaderos[iter->first-t] << endl;

//  if(iter->second[0].f==39)e_region[(iter->second)[0].region]++;

cout << __LINE__ << endl;

  }


//cout << __LINE__ << endl;
    estad_r << "id,cantidad,region,obtenido,verdadero" << endl;

/*
  for(iter_a=e_ataque.begin();iter_a!=e_ataque.end();iter_a++){

    estad_r << iter_a->first << "," << iter_a->second << endl;

//cout << __LINE__ << endl;
  }
*/


cout << __LINE__ << endl;


  for(iter_e=e_region.begin();iter_e!=e_region.end();iter_e++){


cout << __LINE__ << endl;
//cout << (iter_e->first-t) << endl;
 //cout << iter_e->first << "..."<< iter_e->second << "..." << ids[iter_e->first][0].region << endl;
 //cout << __LINE__ << endl;

    estad_r << iter_e->first << "," << iter_e->second << "," << verdaderos[iter_e->first-t] << "," << obtenidos[iter_e->first-t];
    
cout << __LINE__ << endl;
if(!ids[iter_e->first].empty()){

cout << __LINE__ << endl;

    for(it_cel=ids[iter_e->first].begin();it_cel!=ids[iter_e->first].end();it_cel++){

//cout << __LINE__ << endl;

	 estad_r << "," << obtenidos[(it_cel)->id-t] << "," << verdaderos[(it_cel)->id-t]<< " (" << it_cel->id << " - "<< it_cel->distancia << " - " << it_cel->mas_cercana << ")";

         if(verdaderos[(it_cel)->id-t]==0){

            ids[iter_e->first][0].normal++;

	 }else if(verdaderos[(it_cel)->id-t]==-1){

            ids[iter_e->first][0].incierto++;

	 }else{

            ids[iter_e->first][0].anormal++;

	 }

cout << __LINE__ << endl;
    }

}

cout << __LINE__ << endl;
    estad_r << endl;


  }

cout << __LINE__ << endl;
  estad_2 << "id,tamano,normal,anormal,incierto" << endl;
  tasas << "id,tamano,normal,anormal,incierto" << endl;

cout << __LINE__ << endl;
  for(iter_a=e_ataque.begin();iter_a!=e_ataque.end();iter_a++){

    estad_2 << iter_a->first << "," << iter_a->second << endl;
    tasas << iter_a->first << "," << iter_a->second << endl;

  }
vector<double>::iterator iter_tc;
cout << __LINE__ << endl;
int tmt=0;
int cont=0;
  for(iter_2=ids.begin();iter_2!=ids.end();iter_2++){
    cont=0;
//    if(ids[iter_2->first][0].f==-1 && iter_2->first==ids[iter_2->first][0].region){
cout << __LINE__ << endl;

    if(ids[iter_2->first][0].f==-1 && iter_2->first==ids[iter_2->first][0].region){
cout << __LINE__ << endl;
         estad_2 << iter_2->first << "," << ids[iter_2->first].size() << "," << ids[iter_2->first][0].normal << ","  << ids[iter_2->first][0].anormal << "," << ids[iter_2->first][0].incierto << "," << endl;
         tasas << iter_2->first << "," << ids[iter_2->first].size() << "," << ids[iter_2->first][0].normal << ","  << ids[iter_2->first][0].anormal << "," << ids[iter_2->first][0].incierto << ",";


cout << __LINE__ << endl;
        tmt=ids[iter_2->first][0].t_c.size();
	while(cont < tmt){

            tasas <<  ids[iter_2->first][0].t_c[cont] << ",";

            cont++;
         }
         tasas << endl;
	 

    }

cout << __LINE__ << endl;

  }  

cout << endl << "FIN ESTADISTICAS" << endl;

}



void transformacion(map < int, vector<Celula> >& ids,map < int, vector<string> > id_vector){ //mantiene el id y el vector de datos
//map < int, vector<Celula> > transformacion(map < int, vector<Celula> >& ids){

ofstream log("log/transformacion.log",ios::out);

int k;
time_t comienzo, final;
float valor;

cout << "Transformacion con ids size() " << ids.size() << " n: " << n << endl;


//            gsl_vector_free( work );
            gsl_vector_free(V_S);
            gsl_matrix_free( A );
            gsl_matrix_free( R );
            gsl_matrix_free( Original );
            gsl_matrix_free( y );

A = gsl_matrix_alloc( ids.size(), n ); //+1 por la instancia que viene
Original = gsl_matrix_alloc( ids.size(), n ); //+1 por la instancia que viene
V_S = gsl_vector_alloc(n);
y = gsl_matrix_alloc( ids.size(), q );
R=gsl_matrix_alloc(n,n);
//        if(debug==2)
 //          log << "2.2entra aqui con j= " << j << endl;

         map < int, vector<Celula> >::iterator iter4;

         int rr=0; //mide el tamano de ids y A

         if(debug==2)
           log << "2.2: Llego aqui?" << endl;
         //Esto hace el mapeo entre ids y A
	 //

        //if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);
         for(iter4=ids.begin();iter4!=ids.end();iter4++){
//
//           cout << "tamano del vector: "  << id_vector[iter4->first].size() << endl; 
           for(int k=0;k<n;k++){

              valor=atof(id_vector[iter4->first][k].c_str());
//              valor=atof(id_vector[ids[iter4->first][0].id][k].c_str());
              gsl_matrix_set( A, rr, k, valor );

           }

if(debug==1)
           log << endl << "rr: " <<  rr << endl;
	   rr++;


         }

    //if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);
//cout << "rr " << rr <<  endl;


ofstream matrizA("log/matrizA.log",ios::out);

for(int hh=0;hh<rr;hh++){
  for(int kk=0;kk<n;kk++){

    matrizA << gsl_matrix_get(A,hh,kk) << ",";

  }
  matrizA << endl;
}

//     if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);
         if(debug==2){
           log << "2.3: Llego aqui?" << endl;
           log << "tamano de ids segun rr " << rr << endl;
         }

         gsl_matrix_memcpy(Original, A);
         comienzo = time( NULL );





    //if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);

       if(debug!=0)
        log << "Calculando SVD..." << endl;


//         if(  gsl_linalg_SV_decomp( A, R, V_S, work )  ){

         if(  gsl_linalg_SV_decomp_jacobi( A, R, V_S)  ){
            if(debug==2)fprintf( stderr, "fail\n" );
            gsl_vector_free( work );
            gsl_vector_free(V_S);
            gsl_matrix_free( A );
            gsl_matrix_free( R );
            exit( EXIT_FAILURE );
         }

     //if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);
         if(debug==2){
           log << "2-4: Llego aqui?" << endl;
           log << "SVD listo" << endl;
         }
     //if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);
	
         final = time( NULL );

         if(debug==2){
           log << "Tiempo SVD: " << difftime(final, comienzo) << " seg." << endl;
           log << "2.5: Llego aqui?" << endl;
         }
          //Se sacan los valores singulares y los vectores singulares de los representantes

     //if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);
         for (k=0;k<q;k++) {

            if(debug==2)
            log << "\ndimension q: " << k << "\n";

            for (int l=0;l<ids.size();l++){
               gsl_matrix_set(y,l,k,0.0);
               for (int t=0;t<n;t++){
                 gsl_matrix_set(y,l,k,gsl_matrix_get(y,l,k)+gsl_matrix_get(Original,l,t)*gsl_matrix_get(R,t,k));
               }
               gsl_matrix_set(y,l,k,gsl_matrix_get(y,l,k)*(1/gsl_vector_get (V_S,k)));

            } 
         }

     //if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);
         if(debug==2)
           log << "2-6: Llego aqui?" << endl;


         map < int, vector<Celula> >::const_iterator iter2;
         int t=0;

     //if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);

         //Se modifican los valores
         //Pero que pasa con las celulas que ya estan en el grupo, puede que ya no esten en el rango de afinidad...
         for(iter2=ids.begin();iter2!=ids.end();iter2++){

           if(debug==2)
             log << "iter2->first " << iter2->first << endl;

           ids[iter2->first][0].x=gsl_matrix_get(y,t,0);
           ids[iter2->first][0].y=gsl_matrix_get(y,t,1);
           ids[iter2->first][0].z=gsl_matrix_get(y,t,2);
           t++;
	   cout << "t: " << t << endl; 
         }
 
     //if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);

//return ids;



}

std:: string int2string(int n){
std:: stringstream flujo; 
flujo << n;
return(flujo.str());
}
std:: string double2string(double n){
std:: stringstream flujo; 
flujo << n;
return(flujo.str());
}

int main(int argc, char *argv[ ]){

//PARAMETROS
//
//n_watch       : Este es el periodo que el sistema esperara antes de tomar una decision sobre la creacion de un nuevo patron incierto.
//min_count     : El minimo numero de miembros que una patron incierto debe tener, a fin de ser reconocido como un patron normal
//tam_entrenamiento: 
//beta          : Al agregarse una instancia a un conjunto, recalcular el representante dado el parametro 0.0 < beta < 1.0
//tam_max       : Tamano maximo que un grupo puede exceder.


//STL MAPS
//
//id_vector     : mantiene el id de la celula y su correspondiente vector de datos
//ids           : mantiene el id de la celula representante y el grupo de celulas que esta dentro del umbral de afinidad
//
//

//DEBUG
//0: Sin debug
//1: Debug de seguimiento
//2: Debug completo

int id_actual,j,k,n_watch,verificacion,min_count,max_count,tam_entrenamiento,vivas,mas_cercana,recalcular,tam_max,normales, anormales, inciertos, ind_anormal,ind_normal,ind_incierto,ventana,contador_ventana,ind_aborrar,borrados,grafica,finalizar,inciertos_enlinea,envejecido,tipo_inicial,nuevopatron,estatico,n_promedio,t_corte;
float valor,beta,xd,yd,zd,dist_aux,distancia_cercana,tasa_crecimiento;

string linea;
map<int,int> obtenidos;
map<int,int> verdaderos;
map<int,int> tipos_entrenamiento;
map<string,string> p_resumen; 
map< int, vector<string> > id_vector; //mantiene el id y el vector de datos

map <int,int> e_ataque;
map <int,int> e_region;
vector<string> vec;
vector<map < int, vector<Celula> >::const_iterator> aborrar;

time_t comienzo, final, now;
struct tm *tiempoComienzoPtr, *tiempoFinalPtr, *ahoraPtr;
struct tm *tm;
int largo=200;
char *s,*comando;
int etiquetado=0;

now = time ( NULL );
tm = localtime ( &now );

s = new char[largo];

strftime ( s, largo, "%d-%B-%Y_%H-%M-%S", tm );

p_tiempos["t_inicio"]=s;


strftime ( s, largo, "resultados/%d-%B-%Y_%H-%M-%S", tm );
cout << s << endl;


comando = new char[largo];


sprintf(comando,"mkdir -p %s",s);

//system(comando);



ofstream log("log/dinamico.log",ios::out);   //Archivo de debug
ofstream verifica("log/verifica.log",ios::out);   //Archivo de debug
ofstream res("resultados.log",ios::out); //Archivo donde se registraran los resultados
ofstream res2("resultados2.log",ios::out); //Archivo donde se registraran los resultados
ofstream alerta("alerta.log",ios::out); //Archivo que registrara las alarmas nivel 1 y 2
ofstream poblacion("poblacion.log",ios::out); //Cantidad de representantes en cada iteracion
ofstream ind_resultados("indicadores_resultados.csv",ios::out);
ofstream borra2("log/borrados_ids.log",ios::out);
ofstream verd("estadisticas/cells_verd.csv",ios::out);



ifstream r_verdaderos(argv[1]);
ifstream entrenamiento(argv[2]);


cout << "Tipos verdaderos: " << argv[1] << endl;
cout << "Datos entrenamiento: " << argv[2] << endl;


p_resumen["tipos_verdaderos"]=argv[1];
p_resumen["datos_entrenamiento"]=argv[2];
p_resumen["tipos_entrenamiento"]=argv[3];


//cout << __LINE__ << endl;
int transformar=0;
ifstream parametros;

     //if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);
     //
if(strcmp(argv[4],"")==0){
cout << "Parametros: parametros.dat" << endl;
p_resumen["parametros"]="parametros.dat";
parametros.open("parametros.dat");

}else{
p_resumen["parametros"]=argv[4];

cout << "Parametros: " << argv[4] << endl;
parametros.open(argv[4]);

}


map < string , string > param;

if(debug!=0)
log << "PARAMETROS" <<endl;

while(!parametros.eof()){
   getline(parametros,linea);
   split(vec, linea, '=');
   p_resumen[vec[0]]=vec[1];
   param[vec[0]]=vec[1];
   if(debug!=0)
     log << linea << endl;


}


cout << argv[5] << endl;

//cout << __LINE__ << endl;

if(!strcmp(argv[5],"-")){

n_watch=atoi(param["n_watch"].c_str());
min_count=atoi(param["min_count"].c_str());
max_count=atoi(param["max_count"].c_str());
umbral_transformacion=atoi(param["umbral_transformacion"].c_str());
umbral_afinidad=atof(param["umbral_afinidad"].c_str());
envejecido=atoi(param["envejecido"].c_str());
t_corte=atoi(param["t_corte"].c_str());
umbral_reconocimiento=atof(param["umbral_reconocimiento"].c_str());
}else{

vector<string> v(2);

split(v,argv[5],'=');


cout << "Dentro: " << v[0] << " ... " << v[1] << endl;


if(!strcmp(v[0].c_str(),"n_watch")){
	n_watch=atoi(v[1].c_str());
	min_count=atoi(param["min_count"].c_str());
	max_count=atoi(param["max_count"].c_str());
	umbral_transformacion=atoi(param["umbral_transformacion"].c_str());
	umbral_afinidad=atof(param["umbral_afinidad"].c_str());
	envejecido=atoi(param["envejecido"].c_str());

t_corte=atoi(param["t_corte"].c_str());
umbral_reconocimiento=atof(param["umbral_reconocimiento"].c_str());
}

if(!strcmp(v[0].c_str(),"min_count")){
	n_watch=atoi(param["n_watch"].c_str());
	min_count=atoi(v[1].c_str());
	max_count=atoi(param["max_count"].c_str());
	umbral_transformacion=atoi(param["umbral_transformacion"].c_str());
	umbral_afinidad=atof(param["umbral_afinidad"].c_str());
	envejecido=atoi(param["envejecido"].c_str());

	t_corte=atoi(param["t_corte"].c_str());
	umbral_reconocimiento=atof(param["umbral_reconocimiento"].c_str());
}

if(!strcmp(v[0].c_str(),"max_count")){

	n_watch=atoi(param["n_watch"].c_str());
	min_count=atoi(param["min_count"].c_str());
	max_count=atoi(v[1].c_str());
	umbral_transformacion=atoi(param["umbral_transformacion"].c_str());
	umbral_afinidad=atof(param["umbral_afinidad"].c_str());
	envejecido=atoi(param["envejecido"].c_str());

	t_corte=atoi(param["t_corte"].c_str());
	umbral_reconocimiento=atof(param["umbral_reconocimiento"].c_str());
}

if(!strcmp(v[0].c_str(),"umbral_transformacion")){

	n_watch=atoi(param["n_watch"].c_str());
	min_count=atoi(param["min_count"].c_str());
	max_count=atoi(param["max_count"].c_str());
	umbral_transformacion=atoi(v[1].c_str());
	umbral_afinidad=atof(param["umbral_afinidad"].c_str());
	envejecido=atoi(param["envejecido"].c_str());
	t_corte=atoi(param["t_corte"].c_str());
	umbral_reconocimiento=atof(param["umbral_reconocimiento"].c_str());

}

if(!strcmp(v[0].c_str(),"umbral_afinidad")){

	n_watch=atoi(param["n_watch"].c_str());
	min_count=atoi(param["min_count"].c_str());
	max_count=atoi(param["max_count"].c_str());
	umbral_transformacion=atoi(param["umbral_transformacion"].c_str());
	umbral_afinidad=atof(v[1].c_str());
	envejecido=atoi(param["envejecido"].c_str());

	t_corte=atoi(param["t_corte"].c_str());
	umbral_reconocimiento=atof(param["umbral_reconocimiento"].c_str());
}

if(!strcmp(v[0].c_str(),"envejecido")){
	n_watch=atoi(param["n_watch"].c_str());
	min_count=atoi(param["min_count"].c_str());
	max_count=atoi(param["max_count"].c_str());
	umbral_transformacion=atoi(param["umbral_transformacion"].c_str());
	umbral_afinidad=atof(param["umbral_afinidad"].c_str());
	envejecido=atoi(v[1].c_str());
	t_corte=atoi(param["t_corte"].c_str());
	umbral_reconocimiento=atof(param["umbral_reconocimiento"].c_str());
}

if(!strcmp(v[0].c_str(),"umbral_reconocimiento")){

	n_watch=atoi(param["n_watch"].c_str());
	min_count=atoi(param["min_count"].c_str());
	max_count=atoi(param["max_count"].c_str());
	umbral_transformacion=atoi(param["umbral_transformacion"].c_str());
	umbral_afinidad=atof(v[1].c_str());
	envejecido=atoi(param["envejecido"].c_str());

	t_corte=atoi(param["t_corte"].c_str());
	umbral_afinidad=atof(param["umbral_afinidad"].c_str());
	umbral_reconocimiento=atof(v[1].c_str());
}

if(!strcmp(v[0].c_str(),"t_corte")){
	n_watch=atoi(param["n_watch"].c_str());
	min_count=atoi(param["min_count"].c_str());
	max_count=atoi(param["max_count"].c_str());
	umbral_transformacion=atoi(param["umbral_transformacion"].c_str());
	umbral_afinidad=atof(param["umbral_afinidad"].c_str());
	t_corte=atoi(v[1].c_str());
	envejecido=atoi(param["envejecido"].c_str());
	umbral_reconocimiento=atof(param["umbral_reconocimiento"].c_str());
}

}


//cout << __LINE__ << endl;

p_resumen["n_watch"]=int2string(n_watch);
p_resumen["min_count"]=int2string(min_count);
p_resumen["max_count"]=int2string(max_count);
p_resumen["umbral_transformacion"]=int2string(umbral_transformacion);
p_resumen["umbral_afinidad"]=double2string(umbral_afinidad);
p_resumen["envejecido"]=int2string(envejecido);
p_resumen["umbral_reconocimiento"]=double2string(umbral_reconocimiento);


//cout << __LINE__ << endl;

//if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);

int anomalias=atoi(param["anomalias"].c_str());
n_promedio=atoi(param["n_promedio"].c_str());
finalizar=atoi(param["finalizar"].c_str());
estatico=atoi(param["estatico"].c_str());
m=atoi(param["m"].c_str());
tipo_inicial=atoi(param["tipo_inicial"].c_str());
n=atoi(param["n"].c_str());
q=atoi(param["q"].c_str());
tam_max=atoi(param["tam_max"].c_str());



//cout << __LINE__ << endl;
tam_entrenamiento=atoi(param["tam_entrenamiento"].c_str());
ventana=atoi(param["ventana"].c_str());
grafica=atoi(param["grafica"].c_str());
beta=atof(param["beta"].c_str());
tasa_crecimiento=atof(param["tasa_crecimiento"].c_str());

verificacion=atoi(param["verificacion"].c_str());


debug=atoi(param["debug"].c_str());

normales=0;
inciertos=0;
anormales=0;
ind_normal=0;
ind_anormal=0;
ind_incierto=0;
contador_ventana=0;
inciertos_enlinea=0;
normales_enlinea=0;
anormales_enlinea=0;
nuevopatron=0;
e_ataque[-1]=0;
e_ataque[37]=0;
e_ataque[0]=0;

p_resumen["estatico"]=param["estatico"];
cout << "u afinidad: " << umbral_afinidad << endl;
cout << "u reconoci: " << umbral_reconocimiento << endl;
cout << "min_count : " << min_count << endl;
cout << "n_watch   : " << n_watch << endl;
cout << "envejecido: " << envejecido << endl;
cout << "t_corte   : " << t_corte << endl;

//cout << __LINE__ << endl;

if(verificacion!=1){

   verificacion=0;

}

if(anomalias==1){

cout << "Parametro \"anomalias\" activado, se procedera a cambiar los tipos de los ataques a tipo anomalia" << endl;

}

fprintf( stderr, "got to line %d\n", __LINE__ );

int h=0;

if(tipo_inicial=-1){
  
  cout << "Tipos entrenamiento: " << argv[3] << endl;

  ifstream r_entrenamiento(argv[3]);
  h=0;

  while (! r_entrenamiento.eof() ){

    getline (r_entrenamiento,linea);

//  if(anomalias==1&&atoi(linea.c_str())>0){
  if(!strcmp(linea.c_str(),"-") || !strcmp(linea.c_str(),"0")){

    tipos_entrenamiento[h]=0;

  }else{


	if(anomalias==1){

		tipos_entrenamiento[h]=37;

	}else{

    		tipos_entrenamiento[h]=atoi(linea.c_str());
	}




  }
    h++;

  }


}

h=0;
while (! r_verdaderos.eof() ){

  getline (r_verdaderos,linea);

  if(!strcmp("",linea.c_str()))break;

  //if(anomalias==1&&atoi(linea.c_str())>0){

  if(!strcmp(linea.c_str(),"-")||!strcmp(linea.c_str(),"0")){
     verdaderos[h]=0;

  }else{


	if(anomalias==1){
	     verdaderos[h]=37;
	}else{

	     verdaderos[h]=atoi(linea.c_str());
	}

  }
  h++;

}





//cout << __LINE__ << endl;

     //if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);




Celula cell;
Celula test;
map<int,Celula> cells;
map< int, vector<Celula> > ids_log;
map< int, vector<Celula> > ids; //mantiene el id de la celula representante y el grupo de celulas que esta dentro del umbral de afinidad // Se justifica aun mas que sea el primero el representante ya que si se cambia luego, habria que verificar que todas las celulas del grupo quedaran dentro del umbral de afinidad // ?otra forma para revisar anormalidad?
map< int, vector<Celula> > ids_aux;
map< int, vector<Celula> > copia_ids;


//cout << __LINE__ << endl;


gsl_set_error_handler(NULL);
R= gsl_matrix_alloc( n, n );

//cout << __LINE__ << endl;
work = gsl_vector_alloc( n );
V_S = gsl_vector_alloc(n);

y_matrix=gsl_matrix_alloc(1,q);

entrante_matrix=gsl_matrix_alloc(1,n);
/*int tam_entre=0;
while(!entrenamiento.eof()){

getline(entrenamiento,linea);
tam_entre++;

}*/

//cout << tam_entrenamiento << endl;
     //if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);

// a las siguientes tres matrices hay que controlarle el tamano
A = gsl_matrix_alloc( tam_entrenamiento+1, n ); 
Original = gsl_matrix_alloc( tam_entrenamiento+1, n );

y = gsl_matrix_alloc(tam_entrenamiento+1,q);


     //if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);


fprintf( stderr, "got to line %d\n", __LINE__ );
//cout << __LINE__ << endl;
comienzo=time(NULL);

/************INICIO DE ENTRENAMIENTO*********************************/
log << "INICIO DE ENTRENAMIENTO " << argv[2] << endl;
int et=0;
while(!entrenamiento.eof()){

//nnnlog << "Entrenamiento!!!" << endl;
  getline(entrenamiento,linea);
//  cout << linea << endl;
  split(vec, linea, ',');
  
  id_vector[et]=vec;
  for(k=0;k<n;k++){

    valor=atof(vec[k].c_str());
//    cout << valor << endl;
    gsl_matrix_set( A, et, k, valor );

  }

//     if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);
et++;
}
cout << "Numero de datos de entrenamiento: " << (et-1) << endl;

if(et-1!=tam_entrenamiento){

  cout << "Advertencia: El numero de datos de entrenamiento es distinto al suministrado en parametros.dat" << endl;


}

//cout << __LINE__ << endl;
//cout << __LINE__ << endl;


     //if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);
gsl_matrix_memcpy(Original, A);
comienzo = time( NULL );

     //if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);
if(debug!=0) log << "Calculando SVD entrenamiento" << endl;

     //if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);

//cout << __LINE__ << endl;
if( gsl_linalg_SV_decomp_jacobi( A, R, V_S) ){
//if(  gsl_linalg_SV_decomp( A, R, V_S, work )  ){

  if(debug==2)fprintf( stderr, "fail\n" );
  gsl_vector_free( work );
  gsl_vector_free(V_S);
  gsl_matrix_free( A );
  gsl_matrix_free( R );
  exit( EXIT_FAILURE );
}

//cout << __LINE__ << endl;
     //if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);
if(debug!=0)
log << "SVD listo" << endl;
final = time( NULL );

float tiempo_svd = difftime(final,comienzo);

//cout << __LINE__ << endl;

std::stringstream buf;
buf << tiempo_svd;
p_tiempos["t_svd"] = buf.str();


//cout << __LINE__ << endl;

if(debug!=0){
  log << "Tiempo SVD: " << tiempo_svd << " seg." << endl;
}
//Se sacan los valores singulares y los vectores singulares

     //if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);
for (k=0;k<q;k++) {

  if(debug==2)  log << "\ndimension q: " << k << "\n";

  for (int l=0;l<tam_entrenamiento;l++){
      //y[l][k]=0.0;
      gsl_matrix_set(y,l,k,0.0);
      for (int t=0;t<n;t++){
	  //y[l][k] += gsl_matrix_get(Original,l,j)*gsl_matrix_get(V,j,k)
	   gsl_matrix_set(y,l,k,gsl_matrix_get(y,l,k)+gsl_matrix_get(Original,l,t)*gsl_matrix_get(R,t,k)); //Aqui se ocupa la matriz "Original", pues se esta mapeando todas las celulas que se tienen inicialmente
      }
      //y[l][k] *= (1/gsl_vector_get (V_S,k));
      gsl_matrix_set(y,l,k,gsl_matrix_get(y,l,k)*(1/gsl_vector_get (V_S,k)));

  }
}

//cout << __LINE__ << endl;
//cout << __LINE__ << endl;
     //if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);

//Esto se deberia poder juntar con lo anterior para cuando se haga con n dimensiones

if(debug!=0)
log << "Realizando el mapeo de las primeras "<< tam_entrenamiento << "celulas." <<endl;

int t;

for(t=0;t<tam_entrenamiento;t++){
  //cout << "t: " << t << endl;
  cell.id=t;
  cell.x=gsl_matrix_get(y,t,0);
  cell.y=gsl_matrix_get(y,t,1);
  cell.z=gsl_matrix_get(y,t,2);
  cell.region=t;
  cell.tamano_anterior=0;
  cell.edad=0;
  cell.mas_cercana=-1;
  cell.clasifica=0;

     cell.f=tipos_entrenamiento[t]; //Las primeras son todas de acuerdo al tipo dado
  if(cell.f==0){

	normales_enlinea++;

  }else{

	anormales_enlinea++;

  }

  ids[t].push_back(cell); 

if(debug==2)
  log << cell.id << " " << "Cell.x = " << cell.x << "; Cell.y = " << cell.y << "; Cell.z = " << cell.z << endl;

  vivas++;
}

if(debug!=0){
  log << "Mapeo FINALIZADO" << endl;
  log << "ids size = " << ids.size() << endl;
}

 
//cout << __LINE__ << endl;

final=time(NULL);

log << "t pre apoptosis: " << t << endl;
/************FIN DE ENTRENAMIENTO************************************/

char aux[10];

sprintf(aux,"%f",difftime(final,comienzo));

p_tiempos["t_entrenamiento"]=aux;


//RECORDAR: borrar las que no sirvan de id_vector
copia_ids=ids;
ids=apoptosis(ids);
ids=inmunizacion(ids,copia_ids);



cout << "Fin entrenamiento con  #celulas: " << ids.size() << endl;

     //if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);


log << "t post apoptosis: " << t  << "et: " << et << endl;


j=t;


ofstream log_problema("log/problema.log",ios::out);

log_problema << "j inicial: " << j << endl;
cout << "j inicial: " << j << endl;



vector<string> vec2(n);



//ofstream iv("log/verdaderos.data",ios::out);
cout << "Tamano a analizar: " << verdaderos.size()<< endl;

map<int,int>::const_iterator ayua;


int tamano=verdaderos.size();


//cout << __LINE__ << endl;
//INICIO

while(true){


log << "j: " << j << "t: " << t << "j-t = " << j-t << endl;

//cout << "j: " << j << " t: " << t << " j-t: "<< j-t << " verdaderos.size()=" << verdaderos.size() << " tamano: " << tamano << endl;

if(j-t==tamano){
break;
}


//cout << __LINE__ << endl;
if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);

cin >> linea;

//cout << j << " " << "Linea: " << linea << endl;
if(debug!=0) log << "PRINCIPIO j= " << j << endl;


vec2.clear();
split(vec2, linea, ',');


if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);

log_problema << j << " - " << linea << endl;

id_vector[j]=vec2;




if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);







    //if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);
//RECONOCIMIENTO
//1. Se transforma la instancia entrante en una celula
//2. Se revisa si la celula tiene afinidad con alguna existente (Dado el umbral de afinidad)
//2.1 Si no es reconocida por ninguna, se agrega a la matriz se le tipifica como incierto, se agrega a la matriz, 
//se recalcula el SVD y se realiza el calculo nuevamente de las celulas.
//2.2 Si es reconocida se etiqueta con tipo de la cual se reconocio (se dejara que el primero sea el representante del grupo? por mientras si.).


//1. Se transforma la instancia entrante en una celula
//

    //if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);
if(debug!=0){
  log << "RECONOCIMIENTO..." << endl;
  log << "Convirtiendo vector entrante en matriz gsl" << endl;
}

//cout << __LINE__ << endl;

  for(k=0;k<n;k++){
      valor=atof(vec2[k].c_str());

//      log << k << " valor: " << valor << endl;
      gsl_matrix_set( entrante_matrix, 0, k, valor );

  }

    //if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);
//     if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);
if(debug!=0)log << "Cambiando a 3 dimensiones" << endl;


//cout << __LINE__ << endl;
  for (k=0;k<q;k++) {

    if(debug==2)log << "\ndimension q: " << k << " Valor Singular "  << gsl_vector_get(V_S,k) << "\n";


     gsl_matrix_set(y_matrix,0,k,0.0);
  
     for (int pp=0;pp<n;pp++){
       //cout << pp << endl;
       gsl_matrix_set(y_matrix,0,k,gsl_matrix_get(y_matrix,0,k)+gsl_matrix_get(entrante_matrix,0,pp)*gsl_matrix_get(R,pp,k));

     }
     //cout << "Dentro: " << gsl_matrix_get(y,l,k) << endl;
     gsl_matrix_set(y_matrix,0,k,gsl_matrix_get(y_matrix,0,k)*(1/gsl_vector_get (V_S,k)));

  }

//cout << __LINE__ << endl;
  test.id=j;
  test.x=gsl_matrix_get(y_matrix,0,0);
  test.y=gsl_matrix_get(y_matrix,0,1);
  test.z=gsl_matrix_get(y_matrix,0,2);
  test.edad=0;
  test.tamano_anterior=0;
  test.normal=0;
  test.anormal=0;
  test.incierto=0;
  test.clasifica=0;

//cout << __LINE__ << endl;


   // if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);
if(debug!=0)log << "Conversion terminada" << endl;

if(debug==2)log << "x: " << test.x << "y: " << test.y << "z: " << test.z <<endl;

//2. Se revisa si la celula tiene afinidad con alguna existente (Dado el umbral de afinidad)
//Se busca la mas cercana 

distancia_cercana=1000;
mas_cercana=-1;



//cout << __LINE__ << endl;
//     if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);

//aqui hay que iterar sobre ids[i][0]

    if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);
map < int, vector<Celula> >::const_iterator iter;

//cout << __LINE__ << endl;
  for(iter=ids.begin();iter!=ids.end();iter++){ // hasta m??
      xd=ids[iter->first][0].x-test.x;
      yd=ids[iter->first][0].y-test.y;
      zd=ids[iter->first][0].z-test.z;
      dist_aux=xd*xd+yd*yd+zd*zd;
      dist_aux=sqrt(dist_aux);

      if(dist_aux<distancia_cercana){
         mas_cercana=iter->first;
         distancia_cercana=dist_aux;
      }
  }
//2.1 Si es reconocida se etiqueta con tipo de la cual se reconocio (se dejara que el primero sea el representante del grupo? por mientras si. arriba se dieron mas motivos)


verd << test.x << " " << test.y << " " << test.x << " " << verdaderos[test.id-t] << endl;


//cout << __LINE__ << endl;

if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);
//     if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);
if(debug==2)log << "La mas cercana a la celula con id " << test.id << " es " << mas_cercana << " con distancia " << distancia_cercana<< endl;


//cout << __LINE__ << endl;
    //if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);

if(distancia_cercana < umbral_reconocimiento || estatico == 1){
test.mas_cercana=mas_cercana;
test.distancia=distancia_cercana;

//cout << __LINE__ << endl;


     if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);
if(debug==2)
log << "La distancia de la mas cercana es menor que el umbral de afinidad, con: " << distancia_cercana << endl;

//Se etiqueta con la que se encuentra

   test.f=ids[mas_cercana][0].f;

   obtenidos[test.id-t]=test.f;

//cout << __LINE__ << endl;

//Se guarda la celula en el grupo del mas cercano


  log << "#jiturbe: " << test.id << " es cercana a " << ids[mas_cercana][0].id << ", tipo: " << ids[mas_cercana][0].f << ", region:" << ids[mas_cercana][0].region << endl;


    ids[mas_cercana][0].clasifica++;
switch(test.f){

case 0:
    ids[mas_cercana][0].edad=0;
    e_ataque[0]++;
    normales++;
    ind_normal++;
    break;
case -1:
    test.region=ids[mas_cercana][0].region;
    e_region[test.region]++;
    ids[test.id].push_back(test);
    ids[ids[mas_cercana][0].region].push_back(test);
if(debug==1)
    ids_log[ids[mas_cercana][0].region].push_back(test);

    inciertos_enlinea++;
    inciertos++;
    ind_incierto++;
    e_ataque[-1]++; 
    break;
default:
    e_ataque[37]++;
    anormales++;
    ind_anormal++;
}


//cout << __LINE__ << endl;
   if(ids[mas_cercana].size()>tam_max){ //Esto es para tener control de los grupos, para que no excedan cierto tamano

      if(debug==2)
        log << "Se ha excedido tamano maximo" << endl;

   }

    if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);

res << test.id << "," << test.f << endl ;

    //if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);


    if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);


}else{
    //2.2 Si no es reconocida por ninguna, se agrega a la matriz y se le tipifica como incierto.
    //se recalcula el SVD y se realiza el calculo nuevamente de las celulas.

//NOTA: pueden haber problemas en la ejecucion, dado que no se esta manejando el crecimiento de la matriz A.
//R: se puede establecer una cota maxima, la cual si se pasa se realiza apoptosis
test.mas_cercana=-1;
test.distancia=-1;

//cout << __LINE__ << endl;
    e_ataque[-1]++; 

     if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);
  if(debug==2)
   log << "La distancia de la mas cercana es mayor al umbral de afinidad" << endl;

  test.region=test.id;
e_region[test.region]=1;

//cout << __LINE__ << endl;
  test.f=-1; //Es incierta
  inciertos_enlinea++;
  obtenidos[test.id-t]=-1;
  inciertos++;
  ind_incierto++;
  alerta << "ALERTA 1: La celula id: " << test.id << " es incierta." << endl;

   if(debug==2)log << "ALERTA 1: La celula id: " << test.id << " es incierta." << endl;
if(debug==1)
  ids_log[j].push_back(test);
  ids[j].push_back(test); // j????
  ids[j][0].grupo++;

}


//cout << __LINE__ << endl;
/**revisando la tasa de creciemiento**/
map < int, vector<Celula> >::iterator iter3;
float t_c2;

vector<Celula>::iterator iterador_v;

//cout << "Entrando a validar " << __LINE__ << endl;

//log << "t es " << t << endl;
int cont_n=0;
int cont_a=0;


//cout << __LINE__ << endl;
    if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);
for(iter3=ids.begin();iter3!=ids.end();iter3++)
{

//cout << __LINE__ << endl;
    ids[iter3->first][0].edad++;
//cout << iter3->first << endl;
if(ids[iter3->first][0].f==-1)

if(debug==1)   
    verifica << ids[iter3->first][0].f << "==-1" << " && " << ids[iter3->first][0].region << " == " << iter3->first << endl;

//cout << __LINE__ << endl;
//cout << ids[iter3->first][0].region << "----" << iter3->first << " :: " << ids[iter3->first].size()  << endl;
    if(ids[iter3->first][0].f==-1 && ids[iter3->first][0].region==iter3->first && ids[iter3->first].size() >= n_watch) //Solo evalue regiones
    {

			int cont_n=0;
			int cont_a=0;

//cout << __LINE__ << endl;

verifica << "Edad : " << ids[iter3->first][0].edad << ",tam: " << ids[iter3->first].size()  << ",verdadero: " << verdaderos[iter3->first-t];
	if(ids[iter3->first][0].edad < min_count  ){

verifica << ",obtenido: 37,";
		for(int ii=0;ii<ids[iter3->first].size();ii++){

		 		   int idd=ids[iter3->first][ii].id-t;

				   if(verdaderos[idd]==0){
					cont_n++;
				   }else{
					cont_a++;
				   }

		    		   etiquetado++;
				   inciertos_enlinea--;

				   ids[ids[iter3->first][ii].id][0].f=37;
                		   ids[iter3->first][ii].f=37;           
				   ids[iter3->first][ii].edad=0;           
		    		   e_ataque[37]++; 
  				   obtenidos[idd]=37;
				   anormales_enlinea++;

		}   

	verifica << "con_n=" << cont_n << ",cont_a=" << cont_a << endl;

	}else{

//cout << __LINE__ << endl;
verifica << ",obtenido: 0,";
		for(int ii=0;ii<ids[iter3->first].size();ii++){

		   		   int idd=ids[iter3->first][ii].id-t;
   				   //tasa << "(o:" << obtenidos[idd] << " --- v: " << verdaderos[idd] << endl;

				   if(verdaderos[idd]==0){
					cont_n++;
				   }else{
					cont_a++;
				   }

				   etiquetado++;
				   inciertos_enlinea--;

		                   e_ataque[0]++;
				   ids[ids[iter3->first][ii].id][0].f=0;
		                   ids[iter3->first][ii].f=0;
				   ids[iter3->first][ii].edad=0;           
				   obtenidos[idd]=0;
				   normales_enlinea++;
		}

	verifica << "con_n=" << cont_n << ",cont_a=" << cont_a << endl;

	}

    }

//cout << __LINE__ << endl;
//1cout << __LINE__ << endl;
	if(ids[iter3->first][0].f==-1 && ids[iter3->first][0].region==iter3->first && ids[iter3->first][0].edad>=t_corte){ //Solo evalue regiones

//cout << __LINE__ << endl;
//cout << __LINE__ << endl;
verifica << "Edad : " << ids[iter3->first][0].edad; 
verifica << ",tam: " << ids[iter3->first].size();
verifica  << ",verdadero: " << verdaderos[iter3->first-t];
verifica << ", - Tiempo de corte!!!: " << t_corte; 
verifica << ", obtenido: 37,";
		for(int ii=0;ii<ids[iter3->first].size();ii++){

		   		   int idd=ids[iter3->first][ii].id-t;
   				   //tasa << "(o:" << obtenidos[idd] << " --- v: " << verdaderos[idd] << endl;

				   if(verdaderos[idd]==0){
					cont_n++;
				   }else{
					cont_a++;
				   }

//				   etiquetado++;
				   inciertos_enlinea--;

		                   e_ataque[37]++;
				   //ids.erase(ids[iter3->first][ii].id);
				   ids[ids[iter3->first][ii].id][0].f=37;
		                   ids[iter3->first][ii].f=37;
				   ids[iter3->first][ii].edad=0;           
				   obtenidos[idd]=37;
				   anormales_enlinea++;
		}
	verifica << "con_n=" << cont_n << ",cont_a=" << cont_a << endl;
	}
}
//cout << __LINE__ << endl;


/*

    if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);
//VERIFICACION

//1. Verificar que las edades de cada celula (conjunto) del FIN sea menor a n_watch
//     if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);
//1.1 Incrementar edad de cada conjunto representado por la celula en el FIN
//1.2 Si una celula tiene mayor edad a n_watch
//1.2.1 Si su ids[i].size() > min_count => se convierte en un conjunto normal y ?se borra el conjunto y se deja solo el representante?
//1.2.2 Si su ids[i].size() < min_count => Todos sus miembros son etiquetados como anomalos y se activa la alarma 2. y ? se borra la 
//celula (se mata la celula)? y se recalcula el SVD.


//if(j>inicio_del_fin){
//1. Verificar que las edades de cada celula (conjunto) del FIN sea menor a n_watch
//

*/
    if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);

//cout << __LINE__ << endl;
    //if(debug==2)fprintf(stderr,"got to line %d\n",__LINE__);

 ofstream indicadores("indicadores.log",ios::out);
 indicadores << "Numero de paquete " << j << " de " << (verdaderos.size()+tam_entrenamiento-1)  << endl;
 indicadores << "Cantidad de celulas representantes " << ids.size() << endl;
 indicadores << "Celulas inciertas   : " << inciertos_enlinea << endl;
 indicadores << "Celulas etiquetadas : " << etiquetado << endl;
 indicadores << "Celulas normales    : " << normales_enlinea << endl;
 indicadores << "Celulas anormales   : " << anormales_enlinea << endl;


 indicadores << "Normales : " << normales << endl;
 indicadores << "Inciertos: " << inciertos << endl;
 indicadores << "Anormales: " << anormales << endl << endl;
 indicadores << "De los ultimos " << n_watch << ", " << ind_anormal << " son anormales. " << endl;
 indicadores << "De los ultimos " << n_watch << ", " << ind_incierto << " son inciertos. " << endl;
 indicadores << "De los ultimos " << n_watch << ", " << ind_normal << " son normales. " << endl << endl;
// indicadores << "Cantidad a borrar: " << ind_aborrar << endl;
// indicadores << "Borrados reales  : " << borrados << endl << endl;
 
// indicadores << "Tipo obtenido  : " << obtenidos[j] << endl << endl;
// indicadores << "Tipo verdadero : " << verdaderos[j] << endl << endl;

//cout << __LINE__ << endl;
ind_resultados << j << ","<< normales << "," << inciertos << "," << anormales << "," << ids.size() << "," << inciertos_enlinea << endl; 

//cout << __LINE__ << endl;
if(grafica==1){
  cout << ids.size() << endl;
}
if(etiquetado>umbral_transformacion){
cout << "reorganizacion" << endl;
   copia_ids=ids;
cout << "	apoptosis" << endl;
   ids=apoptosis(ids);
cout << "	inmunizacion" << endl;
   ids=inmunizacion(ids,copia_ids);
  etiquetado=0;
cout << "fin reorganizacion" << endl;
}


 contador_ventana++;

 if(contador_ventana == n_watch){

  ind_anormal=0;
  ind_incierto=0;
  ind_normal=0;
  contador_ventana=0;

 }
//}

 j++;


}

now = time ( NULL );
tm = localtime ( &now );


strftime ( s, largo, "%d-%B-%Y_%H-%M-%S", tm );

p_tiempos["t_final"]=s;

sprintf(aux,"%d",inciertos);

p_tiempos["inciertos"]=aux;

sprintf(aux,"%d",normales);

p_tiempos["normales"]=aux;

sprintf(aux,"%d",anormales);

p_tiempos["anormales"]=aux;


sprintf(aux,"%d",ids.size());

p_tiempos["tam_ids_final"]=aux;


//cout << __LINE__ << endl;



final = time( NULL );

float tiempo_total = difftime(final,comienzo);

//cout << __LINE__ << endl;

buf << tiempo_total;
p_tiempos["t_total"] = buf.str();


p_resumen["t_total"] = buf.str();


//cout << __LINE__ << endl;
resume(verdaderos,obtenidos,p_resumen,t);
//cout << __LINE__ << endl;
celulas(ids);
//cout << __LINE__ << endl;
//cout << __LINE__ << endl;

cout << "calculando estadisticas" << endl;

//if(anomalias==0)
//estadisticas(ids_log,verdaderos,obtenidos,t,e_ataque,e_region);
cout << endl;


return 0;
}












